#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
视频转GIF工具
从指定时间点开始将视频转换为GIF动图
"""

import cv2
from PIL import Image
import os


def video_to_gif(video_path, output_path, start_time=12, fps_reduction=1, max_width=480):
    """
    将视频转换为GIF
    
    参数:
        video_path: 输入视频路径
        output_path: 输出GIF路径
        start_time: 开始时间(秒)
        fps_reduction: 帧率降低倍数,越大生成的GIF越小(例如:2表示每2帧取1帧)
        max_width: GIF最大宽度,会按比例缩放高度
    """
    
    # 检查视频文件是否存在
    if not os.path.exists(video_path):
        print(f"错误: 视频文件不存在: {video_path}")
        return False
    
    # 打开视频文件
    cap = cv2.VideoCapture(video_path)
    
    if not cap.isOpened():
        print(f"错误: 无法打开视频文件: {video_path}")
        return False
    
    # 获取视频信息
    fps = int(cap.get(cv2.CAP_PROP_FPS))
    total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    duration = total_frames / fps
    
    print(f"视频信息:")
    print(f"  FPS: {fps}")
    print(f"  总帧数: {total_frames}")
    print(f"  时长: {duration:.2f}秒")
    
    # 计算开始帧
    start_frame = int(start_time * fps)
    
    if start_frame >= total_frames:
        print(f"错误: 开始时间({start_time}秒)超过视频总时长({duration:.2f}秒)")
        cap.release()
        return False
    
    # 跳转到开始帧
    cap.set(cv2.CAP_PROP_POS_FRAMES, start_frame)
    print(f"\n从第 {start_time} 秒开始提取帧...")
    
    frames = []
    frame_count = 0
    extracted_count = 0
    
    while True:
        ret, frame = cap.read()
        if not ret:
            break
        
        # 按fps_reduction降低帧率
        if frame_count % fps_reduction == 0:
            # OpenCV读取的是BGR,转换为RGB
            frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            
            # 调整大小
            height, width = frame_rgb.shape[:2]
            if width > max_width:
                scale = max_width / width
                new_width = max_width
                new_height = int(height * scale)
                frame_rgb = cv2.resize(frame_rgb, (new_width, new_height))
            
            # 转换为PIL Image
            pil_image = Image.fromarray(frame_rgb)
            frames.append(pil_image)
            extracted_count += 1
            
            if extracted_count % 10 == 0:
                print(f"  已提取 {extracted_count} 帧...")
        
        frame_count += 1
    
    cap.release()
    
    if len(frames) == 0:
        print("错误: 没有提取到任何帧")
        return False
    
    print(f"\n总共提取了 {len(frames)} 帧")
    
    # 计算GIF的FPS
    gif_fps = fps / fps_reduction
    duration_per_frame = int(1000 / gif_fps)  # 毫秒
    
    print(f"正在生成GIF...")
    print(f"  GIF帧率: {gif_fps:.1f} FPS")
    print(f"  每帧间隔: {duration_per_frame} 毫秒")
    
    # 确保输出目录存在
    os.makedirs(os.path.dirname(output_path), exist_ok=True)
    
    # 保存为GIF
    frames[0].save(
        output_path,
        save_all=True,
        append_images=frames[1:],
        duration=duration_per_frame,
        loop=0,  # 0表示无限循环
        optimize=True
    )
    
    # 获取文件大小
    file_size = os.path.getsize(output_path) / (1024 * 1024)  # MB
    print(f"\nGIF生成成功!")
    print(f"  保存路径: {output_path}")
    print(f"  文件大小: {file_size:.2f} MB")
    
    return True


if __name__ == "__main__":
    # 输入视频路径
    video_path = "/home/ubuntu/文档/xwechat_files/wxid_6pzxwc8xatm122_cdc5/msg/video/2025-11/406dbe1cee867df7e97ba6ae83deebbc.mp4"
    
    # 输出GIF路径
    output_path = "/home/ubuntu/文档/output.gif"
    
    # ========== 可调节参数 ==========
    start_time = 12           # 从第12秒开始
    fps_reduction = 10         # 帧率降低倍数(1=不降低, 2=每2帧取1帧, 3=每3帧取1帧...)
    max_width = 480          # GIF最大宽度(像素)
    # ==============================
    
    print("=" * 60)
    print("视频转GIF工具")
    print("=" * 60)
    print(f"\n参数设置:")
    print(f"  开始时间: {start_time} 秒")
    print(f"  帧率降低: 每 {fps_reduction} 帧取 1 帧")
    print(f"  最大宽度: {max_width} 像素")
    print()
    
    # 转换视频
    success = video_to_gif(
        video_path=video_path,
        output_path=output_path,
        start_time=start_time,
        fps_reduction=fps_reduction,
        max_width=max_width
    )
    
    if success:
        print("\n转换完成! ✓")
    else:
        print("\n转换失败! ✗")